/*
 * WebQueryWorkbench.java
 *
 * Created on March 27, 2005, 12:26 AM
 */

package tools;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;
import java.util.Properties;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import org.w3c.dom.Node;
import util.RemoveNullFilterInputStream;

/**
 *
 * @author Keith
 */
public class WebQueryWorkbench extends JPanel  {
  
  private JTabbedPane tabPane = new JTabbedPane();
  private Map actions;
  private UrlProcess urlProcess;
  private HtmlProcess htmlProcess;
  private XhtmlProcess xhtmlProcess;
  private LogProcess logProcess;
  private XslProcess xslProcess;
  private XmlProcess xmlProcess;
  private StockProcess stockProcess;

  public WebQueryWorkbench() {
    setLayout( new BorderLayout() );
    JPanel southPanel = new JPanel( new FlowLayout( FlowLayout.CENTER ) );

    southPanel.setBackground( Color.lightGray );
    southPanel.setBorder(
      BorderFactory.createTitledBorder(
            BorderFactory.createCompoundBorder(
                  BorderFactory.createBevelBorder( javax.swing.border.BevelBorder.RAISED ),
                  BorderFactory.createEmptyBorder( 2, 3, 3, 3 ) ),
      "Process Flow", javax.swing.border.TitledBorder.LEFT,
        javax.swing.border.TitledBorder.BELOW_TOP ) );
    JPanel p = new HtmlExtractorProcess( );

    southPanel.add( p );

    add( tabPane, BorderLayout.CENTER );
    add( southPanel, BorderLayout.SOUTH );

    urlProcess = new UrlProcess();
    urlProcess.addActionListener( new ActionListener(){
      public void actionPerformed( ActionEvent e ){
        getHtmlPerformed( e );
      }
    } );

    htmlProcess = new HtmlProcess();
    htmlProcess.addActionListener( new ActionListener(){
      public void actionPerformed( ActionEvent e ){
        generateXhtmlPerformed( e );
      }
    } );

    logProcess = new LogProcess();
    xhtmlProcess = new XhtmlProcess();
    xslProcess = new XslProcess();

    ActionListener generateXmlListener = new ActionListener(){
      public void actionPerformed( ActionEvent e ){
        generateXmlPerformed( e );
      }
    };

    xhtmlProcess.addActionListener( generateXmlListener );
    xslProcess.addActionListener( generateXmlListener );

    stockProcess = new StockProcess();
    stockProcess.addActionListener( new ActionListener(){
      public void actionPerformed( ActionEvent e ){
        generateUrlPerformed( e );
      }
    } );


    xmlProcess = new XmlProcess();
    tabPane.add( stockProcess );
    tabPane.add( urlProcess );
    tabPane.add( htmlProcess );
    tabPane.add( logProcess );
    tabPane.add( xhtmlProcess );
    tabPane.add( xslProcess );
    tabPane.add( xmlProcess );

    Component[] c = tabPane.getComponents();
    ComponentListener cl = new ComponentAdapter(){
      public void componentHidden(ComponentEvent e){
//        System.out.println( "Hidden: " + e.getComponent().getName() );
        setActions( null );
      }

      public void componentShown(ComponentEvent e){
//        System.out.println( "Shown: " + e.getComponent().getName() );
        Object o = (Object)e.getSource();
        Map m = null;

        if ( o instanceof ProcessPanel ){
          ProcessPanel p = (ProcessPanel)o;

          m = p.getActions();
        }

        setActions( m );
      }
    };

    for ( int i = 0; i < c.length; i++ ){
      c[ i ].addComponentListener( cl );
    }
  }

  public Map getActions() {
    return actions;
  }

  public void setActions( Map newActions) {
    Map  oldActions = actions;
    this.actions = newActions;
    firePropertyChange("actions", oldActions, newActions);
  }

  protected void getHtmlPerformed( ActionEvent e ){
//    System.out.println( "getHtmlRequested: e = " + e );

    UrlProcess p = (UrlProcess)e.getSource();
    UrlProcessModel m = p.getModel();

    if ( m.isUseProxy() ){
      try {
        URL proxy = new URL( m.getProxyUrl() );

        Properties sysProps = System.getProperties();
        sysProps.put( "proxySet", "true" );
        sysProps.put( "proxyHost", proxy.getHost() );
        sysProps.put( "proxyPort", String.valueOf( proxy.getPort() ) );
      } catch ( MalformedURLException ex ){
        System.out.println( "Invalid proxy URL: " + m.getProxyUrl() );
      }
    }

    BufferedInputStream is = null;
    OutputStream os = null;

    try {
      URL htmlUrl = new URL( m.getHtmlUrl() );

      is = new BufferedInputStream( new RemoveNullFilterInputStream( htmlUrl.openStream() ) );
      os = htmlProcess.getOverwriteOutputStream();
      tabPane.setSelectedComponent( htmlProcess );

      int bytesRead;
      byte[] buf = new byte[ 1024 ];
      while ( ( bytesRead = is.read( buf ) ) != -1 ){
        os.write( buf, 0, bytesRead );
      }
      os.close();
    } catch ( MalformedURLException ex ){
      System.out.println( "Invalid html URL: " + m.getHtmlUrl() );
    } catch ( IOException ex ){
      ex.printStackTrace();
    } finally {
      if ( is != null ){
        try { is.close(); } catch ( IOException ex ){}
      }
      if ( os != null ){
        try { os.close(); } catch ( IOException ex ){}
      }
    }
  }

  protected void generateXhtmlPerformed( ActionEvent e ){
//    System.out.println( "getHtmlRequested: e = " + e );
    org.w3c.tidy.Tidy tidy = new org.w3c.tidy.Tidy();

    tidy.setXHTML( true );
    tidy.setXmlPi( true );
    tidy.setXmlOut( true );
    tidy.setSmartIndent( true );
    tidy.setShowWarnings( true );
    tidy.setMakeClean( true );
    tidy.setQuiet( true );
    tidy.setWraplen( 80 );
    tidy.setNumEntities(true);
    
    PrintWriter pw = new PrintWriter( logProcess.getAppendOutputStream() );
    tidy.setErrout( pw );
tidy.setXmlTags( false );
    tidy.setTabsize( 1 );

    InputStream is = htmlProcess.getInputStream();
    OutputStream os = xhtmlProcess.getOverwriteOutputStream();
    tabPane.setSelectedComponent( xhtmlProcess );

    try {
      tidy.parse( is, os );

      os.close();
      pw.close();
    } catch ( IOException ex ){
      ex.printStackTrace();
    } finally {
      if ( is != null ){
        try { is.close(); } catch ( IOException ex ){}
      }
      if ( os != null ){
        try { os.close(); } catch ( IOException ex ){}
      }
    }
  }

  protected void generateXmlPerformed( ActionEvent e ){
//    System.out.println( e );
    OutputStream xmlOutStream = null;
    OutputStream logStream = logProcess.getAppendOutputStream();

    try {
      xmlOutStream = xmlProcess.getOverwriteOutputStream();
      tabPane.setSelectedComponent( xmlProcess );

      javax.xml.transform.TransformerFactory tFactory =
                  javax.xml.transform.TransformerFactory.newInstance();
/**/
// start
      // Instantiate a DocumentBuilderFactory.
      javax.xml.parsers.DocumentBuilderFactory dfactory =
                          javax.xml.parsers.DocumentBuilderFactory.newInstance();
      // Use the DocumentBuilderFactory to provide access to a DocumentBuilder.
      javax.xml.parsers.DocumentBuilder dBuilder = dfactory.newDocumentBuilder();

      // Use the DocumentBuilder to parse the XML input.
//      System.out.println( "isValidating: " + dBuilder.isValidating() );
      org.w3c.dom.Document inDoc = dBuilder.parse( xhtmlProcess.getInputStream() );

//      dom.Writer writer = new dom.Writer();
//      writer.setOutput( System.out, null );
//      writer.write( inDoc );
// end
/**/
      javax.xml.transform.Transformer transformer = tFactory.newTransformer
                (new javax.xml.transform.stream.StreamSource( xslProcess.getInputStream() ) );

      transformer.clearParameters();
      transformer.setParameter( "symbol", stockProcess.getSymbol() );
      transformer.transform
          (new javax.xml.transform.dom.DOMSource(inDoc),
           new javax.xml.transform.stream.StreamResult( xmlOutStream ) );

    } catch ( org.xml.sax.SAXException ex ){
      ex.printStackTrace();
    } catch ( javax.xml.parsers.ParserConfigurationException ex ){
      ex.printStackTrace();
    } catch ( javax.xml.transform.TransformerConfigurationException ex ){
      ex.printStackTrace();
    } catch ( javax.xml.transform.TransformerException ex ){
      ex.printStackTrace();
    } catch ( IOException ex ){
      ex.printStackTrace();
    } finally {
      if ( xmlOutStream != null ){
        try { xmlOutStream.close(); } catch ( IOException ex ){}
      }
      if ( logStream != null ){
        try { logStream.close(); } catch ( IOException ex ){}
      }
    }
  }

  public void generateUrlPerformed( ActionEvent e ){
//    System.out.println( e );
    OutputStream xmlOutStream = null;
    javax.xml.transform.dom.DOMResult dom = new javax.xml.transform.dom.DOMResult();
    OutputStream logStream = logProcess.getAppendOutputStream();

    try {
      xmlOutStream = System.out;
      tabPane.setSelectedComponent( urlProcess );

      javax.xml.transform.TransformerFactory tFactory =
                  javax.xml.transform.TransformerFactory.newInstance();
/**/
// start
      // Instantiate a DocumentBuilderFactory.
      javax.xml.parsers.DocumentBuilderFactory dfactory =
                          javax.xml.parsers.DocumentBuilderFactory.newInstance();
      // Use the DocumentBuilderFactory to provide access to a DocumentBuilder.
      javax.xml.parsers.DocumentBuilder dBuilder = dfactory.newDocumentBuilder();
      // Use the DocumentBuilder to parse the XML input.
//      System.out.println( "isValidating: " + dBuilder.isValidating() );
      org.w3c.dom.Document inDoc = dBuilder.parse( stockProcess.getInputStream() );

//      dom.Writer writer = new dom.Writer();
//      writer.setOutput( System.out, null );
//      writer.write( inDoc );
// end
/**/
      javax.xml.transform.Transformer transformer = tFactory.newTransformer
                (new javax.xml.transform.stream.StreamSource( stockProcess.getInputStream() ) );

      transformer.clearParameters();
      transformer.setParameter( "symbol", stockProcess.getSymbol() );
      transformer.setParameter( "symbolClass", stockProcess.getSymbolClass() );
      transformer.transform
          (new javax.xml.transform.dom.DOMSource( inDoc ), dom );
//           new javax.xml.transform.stream.StreamResult( xmlOutStream ) );

      dom.Writer writer = new dom.Writer();
      writer.setOutput( System.out, null );
      writer.write( dom.getNode() );

      org.w3c.dom.Document outDoc = (org.w3c.dom.Document)dom.getNode();
      org.w3c.dom.NodeList nl = outDoc.getElementsByTagName( "path" );
      Node urlNode = nl.item( 0 );
      org.w3c.dom.NodeList children = urlNode.getChildNodes();
      StringBuffer urlBuf = new StringBuffer();

      for ( int i = 0; i < children.getLength(); i++ ){
        urlBuf.append( children.item( i ).getNodeValue() );
      }
      String url = urlBuf.toString();
      urlProcess.setHtmlUrl( url );
//      System.out.println( "url: " + url );
    } catch ( org.xml.sax.SAXException ex ){
      ex.printStackTrace();
    } catch ( javax.xml.parsers.ParserConfigurationException ex ){
      ex.printStackTrace();
    } catch ( javax.xml.transform.TransformerConfigurationException ex ){
      ex.printStackTrace();
    } catch ( javax.xml.transform.TransformerException ex ){
      ex.printStackTrace();
    } catch ( IOException ex ){
      ex.printStackTrace();
    } finally {
      if ( xmlOutStream != null ){
        try { xmlOutStream.close(); } catch ( IOException ex ){}
      }
      if ( logStream != null ){
        try { logStream.close(); } catch ( IOException ex ){}
      }
    }

  }
}
